﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using hedefgrup.reports.renault.database;
using hedefgrup.reports.renault.date;

namespace hedefgrup.reports.common
{
    public class Report_DealerInterviewCounts : Report_Abstract
    {
        internal class Storage
        {
            public string Dealer;
            public SortedList<string, float> MonthlyCounts = new SortedList<string, float>();
        }

        private void EnsureExistenceAndAppendCount(SortedList<string, Storage> entityStorage, string entityCode, string yearAndMonth, int count)
        {
            Storage entity = null;
            if (!string.IsNullOrEmpty(entityCode))
            {
                if (!entityStorage.ContainsKey(entityCode))
                {
                    entityStorage.Add(entityCode, entity = new Storage() { Dealer = entityCode });
                }
                else
                {
                    entity = entityStorage[entityCode];
                }
            }
            if (entity != null)
            {
                if (monthlyDatasToAppendAccordingToRoll.ContainsKey(yearAndMonth))
                {
                    foreach (string rolledYearAndMonth in monthlyDatasToAppendAccordingToRoll[yearAndMonth])
                    {
                        if (!entity.MonthlyCounts.ContainsKey(rolledYearAndMonth))
                        {
                            entity.MonthlyCounts.Add(rolledYearAndMonth, count);
                        }
                        else
                        {
                            entity.MonthlyCounts[rolledYearAndMonth] += count;
                        }
                    }
                }
                else
                {
                    if (!entity.MonthlyCounts.ContainsKey(yearAndMonth))
                    {
                        entity.MonthlyCounts.Add(yearAndMonth, count);
                    }
                    else
                    {
                        entity.MonthlyCounts[yearAndMonth] += count;
                    }
                }
            }
        }

        Dictionary<string, List<string>> monthlyDatasToAppendAccordingToRoll;

        private Dictionary<string, List<string>> GetMonthlyDatasToAppendAccordingToRoll()
        {
            int roll = (int)GetCriteriaByName("Roll").ToActualValue();
            reportMonth beginMonth = new reportMonth(GetCriteriaByName("Begin Month").Value);
            reportMonth endMonth = new reportMonth(GetCriteriaByName("End Month").Value);

            Dictionary<string, List<string>> monthlyDatas = new Dictionary<string, List<string>>();

            for (int month = beginMonth.dateValue; month <= endMonth.dateValue; month++)
            {
                reportMonth reportMonthCurrent = new reportMonth(month);
                string reportMonthString = reportMonthCurrent.ToYYYYMM();

                for (int rolledMonths = month - roll; rolledMonths <= month; rolledMonths++)
                {
                    reportMonth rolledMonthCurrent = new reportMonth(rolledMonths);
                    string rolledMonthString = rolledMonthCurrent.ToYYYYMM();
                    if (!monthlyDatas.ContainsKey(rolledMonthString))
                    {
                        monthlyDatas.Add(rolledMonthString, new List<string>());
                        monthlyDatas[rolledMonthString].Add("*");
                    }
                    monthlyDatas[rolledMonthString].Add(reportMonthString);
                }
            }

            return monthlyDatas;
        }

        public override ReportResult GenerateReport()
        {
            ReportResult results = new ReportResult(this);

            monthlyDatasToAppendAccordingToRoll = GetMonthlyDatasToAppendAccordingToRoll();

            Filter yearFilter = GetFilterByName("YIL");
            string yearFilterValueBackup = yearFilter.Values.Count > 0 ? yearFilter.Values[0] : null;
            yearFilter.Values.Clear();
            yearFilter.Values.Add(GetMaxYearForYearlyTotal().ToString());

            DataTable yearData = db.query
            (
                "SELECT YIL = '*', AY = '', " + base.DealerColumn + ", KOORDINATOR, " + AreaColumn + ", CNT = COUNT(*) FROM " + Context.TableName + " " +
                GetSqlStatementFilter(new Criteria[] { GetCriteriaByName("Network"), GetCriteriaByName("Organization") }) +
                " GROUP BY " + base.DealerColumn + ", KOORDINATOR, " + AreaColumn + " ",
                base.GetSqlStatementParameters(new Criteria[] { GetCriteriaByName("Network"), GetCriteriaByName("Organization") })
            );
            if (yearFilterValueBackup != null)
            {
                yearFilter.Values[0] = yearFilterValueBackup;
            }
            else
            {
                yearFilter.Values.Clear();
            }

            DataTable reportData = db.query
            (
                "SELECT YIL, AY, " + base.DealerColumn + ", KOORDINATOR, " + AreaColumn + ", CNT = COUNT(*) FROM " + Context.TableName + " " +
                base.GetSqlStatementFilter() +
                " GROUP BY " + base.DealerColumn + ", YIL, AY, KOORDINATOR, " + AreaColumn + " ",
                base.GetSqlStatementParameters()
            );

            List<string> yearAndMonths = new List<string>();

            SortedList<string, Storage> yearStorage = ToStorage(yearData, yearAndMonths);
            SortedList<string, Storage> reportStorage = ToStorage(reportData, yearAndMonths);

            yearAndMonths.Remove("*");
            yearAndMonths.Sort();

            Row headerRow = new Row();
            results.HeaderRows.Add(headerRow);
            headerRow.Cells.Add(new Cell() { Text = "BAYİİ KODU" });
            headerRow.Cells.Add(new Cell() { Text = "BAYİİ ADI" });
            headerRow.Cells.Add(new Cell() { Text = string.Format("{0}YTD", GetMaxYearForYearlyTotal()) });
            headerRow.Cells.Add(new Cell() { Text = string.Format("{0}YTD", GetMaxYearForYearlyTotal()) });
            foreach (string yearAndMonth in yearAndMonths)
            {
                headerRow.Cells.Add(new Cell() { Text = yearAndMonth });
                headerRow.Cells.Add(new Cell() { Text = yearAndMonth });
            }

            Row countAndPercentageRow = new Row();
            results.HeaderRows.Add(countAndPercentageRow);
            countAndPercentageRow.Cells.Add(new Cell());
            countAndPercentageRow.Cells.Add(new Cell());
            for (int i = 0; i <= yearAndMonths.Count; i++)
            {
                countAndPercentageRow.Cells.Add(new Cell() { Text = "Baz" });
                countAndPercentageRow.Cells.Add(new Cell() { Text = "%" });
            }

            Row totalRow = new Row();
            results.Rows.Add(totalRow);
            totalRow.Cells.Add(new Cell());
            totalRow.Cells.Add(new Cell() { Text = "GENEL", TextAlign = "left" });
            totalRow.Cells.Add(new Cell() { Text = yearStorage.ContainsKey("_TOTAL_") ? yearStorage["_TOTAL_"].MonthlyCounts["*"].ToString() : "" });
            totalRow.Cells.Add(new Cell() { Text = yearStorage.ContainsKey("_TOTAL_") ? string.Format("{0:0.0}", 100f) : "" });
            foreach (string yearAndMonth in yearAndMonths)
            {
                totalRow.Cells.Add(new Cell() { Text = reportStorage["_TOTAL_"].MonthlyCounts[yearAndMonth].ToString() });
                totalRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 100) });
            }

            List<string> mergedDealers = new List<string>();
            if (yearStorage.ContainsKey("_TOTAL_"))
            {
                mergedDealers.AddRange(yearStorage.Keys);
            }
            if (reportStorage != null)
            {
                foreach (string dealerCode in reportStorage.Keys)
                {
                    if (!mergedDealers.Contains(dealerCode))
                    {
                        mergedDealers.Add(dealerCode);
                    }
                }
            }

            foreach (string dealerCode in mergedDealers)
            {
                if (dealerCode == "_TOTAL_")
                {
                    continue;
                }
                Row dealerRow = new Row();
                results.Rows.Add(dealerRow);
                dealerRow.Cells.Add(new DealerCodeCell() { Text = dealerCode, TextAlign = "left" });
                dealerRow.Cells.Add(new Cell() { Text = base.GetDealerName(dealerCode), TextAlign = "left" });
                if (yearStorage != null && yearStorage.ContainsKey(dealerCode) && yearStorage[dealerCode].MonthlyCounts.ContainsKey("*"))
                {
                    float dealerYearCount = yearStorage[dealerCode].MonthlyCounts["*"];
                    float dealerYearTotalCount = yearStorage["_TOTAL_"].MonthlyCounts["*"];
                    dealerRow.Cells.Add(new Cell() { Text = dealerYearCount.ToString() });
                    dealerRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 100 * (dealerYearCount / dealerYearTotalCount)) });
                }
                else
                {
                    dealerRow.Cells.Add(new Cell() { Text = "" });
                    dealerRow.Cells.Add(new Cell() { Text = "" });
                }
                foreach (string yearAndMonth in yearAndMonths)
                {
                    if (reportStorage.ContainsKey(dealerCode) && reportStorage[dealerCode].MonthlyCounts.ContainsKey(yearAndMonth))
                    {
                        float dealerCount = reportStorage[dealerCode].MonthlyCounts[yearAndMonth];
                        float totalCount = reportStorage["_TOTAL_"].MonthlyCounts[yearAndMonth];
                        dealerRow.Cells.Add(new Cell() { Text = dealerCount.ToString() });
                        dealerRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 100 * (dealerCount / totalCount)) });
                    }
                    else
                    {
                        dealerRow.Cells.Add(new Cell() { Text = "0" });
                        dealerRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 0f) });
                    }
                }
            }

            return results;
        }

        private SortedList<string, Storage> ToStorage(DataTable reportData, List<string> yearAndMonths)
        {
            SortedList<string, Storage> dealerStorage = new SortedList<string, Storage>();

            foreach (DataRow reportRow in reportData.Rows)
            {
                string dealerCode = reportRow[base.DealerColumn].ToString().Trim();
                string coordinatorCode = reportRow["KOORDINATOR"].ToString().Trim();
                string areaCode = reportRow[AreaColumn].ToString().Trim();
                int count = Convert.ToInt32(reportRow["CNT"]);
                string yearAndMonth = string.Format("{0:0000}{1:00}", reportRow["YIL"], reportRow["AY"]);

                if (monthlyDatasToAppendAccordingToRoll.ContainsKey(yearAndMonth))
                {
                    foreach (string rolledMonthlyData in monthlyDatasToAppendAccordingToRoll[yearAndMonth])
                    {
                        if (!yearAndMonths.Contains(rolledMonthlyData))
                        {
                            yearAndMonths.Add(rolledMonthlyData);
                        }
                    }
                }

                EnsureExistenceAndAppendCount(dealerStorage, dealerCode, yearAndMonth, count);
                if (CoordinatorsReported)
                {
                    EnsureExistenceAndAppendCount(dealerStorage, coordinatorCode, yearAndMonth, count);
                }
                EnsureExistenceAndAppendCount(dealerStorage, areaCode, yearAndMonth, count);
                EnsureExistenceAndAppendCount(dealerStorage, "_TOTAL_", yearAndMonth, count);
            }

            return dealerStorage;
        }

        public override string DisplayName
        {
            get { return "Bayii Görüşme Adetleri"; }
        }

        public override bool SupportsProject(string projectName)
        {
            return base.SupportsProject(projectName) || projectName == Global.PROJECT_SATIS_SUREC;
        }

        public override string SortPrefix
        {
            get { return "0x05"; }
        }
    }
}
